﻿/*
 * ©2009-2010 XELF
 * http://xelf.info
 */

#if XNA || WINDOWS_PHONE
using _MathHelper = Microsoft.Xna.Framework.MathHelper;
#else
using _MathHelper = XELF.Framework.MathHelper;
#endif

using System;

namespace XELF.Framework {

	public partial struct Quaternion {
		/// <summary>
		/// 球面線形補間
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <param name="amount"></param>
		/// <param name="result"></param>
		public static void Slerp(ref Quaternion a, ref Quaternion b, float amount, out Quaternion result) {
			const float epsilon = 1e-4f;
			var cos = Dot(a, b);
			if (cos >= 1 - epsilon) {
				Lerp(ref a, ref b, amount, out result);
			} else {
				cos = _MathHelper.Clamp(cos, -1, +1);
				var theta = amount * MathHelper.Acos(cos);
				var u = MathHelper.Cos(theta);
				var v = MathHelper.Sin(theta);
				Quaternion q0, q2;
				Multiply(ref a, cos, out q2);
				Subtract(ref b, ref q2, out q2);
				q2.Normalize();
				Multiply(ref a, u, out q0);
				Multiply(ref q2, v, out q2);
				Add(ref q0, ref q2, out result);
			}
		}
	}

	public partial struct Quaternion {
		/// <summary>
		/// 球面線形補間
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <param name="amount"></param>
		/// <returns></returns>
		public static Quaternion Slerp(Quaternion a, Quaternion b, float amount) {
			Quaternion result;
			Slerp(ref a, ref b, amount, out result);
			return result;
		}
	}

}
